package com.lmf.juc.Lock.case5;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 演示可重入锁：可重入就是说某个线程已经获得某个锁，可以再次获取锁而不会出现死锁
 *
 * （1）synchronized，Lock，两者都是可重入锁，也叫递归锁。
 * （2）sychronized是隐式锁，不用手工上锁与解锁，而lock为显示锁，需要手工上锁与解锁
 */
public class SynchronizedLockDemo {

    //创建可重入锁
    private static Lock lock = new ReentrantLock();//默认是非公平锁
    private static Lock lock1 = new ReentrantLock();//默认是非公平锁

    public static void main(String[] args) {

//        Object o = new Object();
//        new Thread(() -> {
//            //使用同步代码块
//            synchronized (o){
//                System.out.println(Thread.currentThread().getName() + "：外层锁");
//                synchronized (o){
//                    System.out.println(Thread.currentThread().getName() + "：中层锁");
//                    synchronized (o){
//                        System.out.println(Thread.currentThread().getName() + "：内层锁");
//                    }
//                }
//            }
//        },"aa").start();

        //调用递归锁方法
//        add();

        //调用Lock演示的可重入锁
        addLock();
    }

    //创建递归调用锁方法：会报栈溢出
    public static synchronized void add(){
        System.out.println(Thread.currentThread().getName() + "：外层锁");
        SynchronizedLockDemo.add();
    }

    public static void addLock(){
        try {
            //上锁
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "：外层锁");
            try {
                //上锁
                lock.lock();
                System.out.println(Thread.currentThread().getName() + "：中层锁");
                try {
                    //上锁
                    lock.lock();
                    System.out.println(Thread.currentThread().getName() + "：内层锁");
                }finally {
                    //解锁
                    lock.unlock();
                }
            }finally {
                //解锁
                lock.unlock();
            }
        }finally {
            //解锁
            lock.unlock();
        }
    }
}
